package com.ajx.platform.buildingmronitor.websocket;


import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 继承Application接口后项目启动时会按照执行顺序执行run方法
 * 通过设置Order的value来指定执行的顺序，默认最低优先级
 */
@Component
@Order
public class EventServer implements ApplicationRunner {
    private Logger logger = LoggerFactory.getLogger(EventServer.class);
    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.info("hello world!");

        // 创建一个基于HTTP协议的 jetty Servlet server
        Server server = new Server();
        // jetty网络接口封装，用于监听网络请求
        ServerConnector connector = new ServerConnector(server);
        // 设置该server监听端口
        connector.setPort(50001);
        // 将网络配置加入server 容器中
        server.addConnector(connector);
        logger.info("hello world 22!");

        // Setup the basic application "context" for this application at "/"
        // This is also known as the handler tree (in jetty speak)
        // 当connector收到请求的时候，就必须要有处理器来处理请求
        // Handler:处理器，继承abstractHandler这个抽象类，这是因为abstractHandler里面有个重要的方法来处理请求。
        // jetty中使用servlet:
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        // 设置访问路径
        context.setContextPath("/");
        server.setHandler(context);
        logger.info("hello world 33!");


        // Add a websocket to a specific path spec
        ServletHolder holderEvents = new ServletHolder("ws-events", EventServlet.class);
        // 添加servlet采用的是addServlet的方式，里面需要实例ServletHolder
        context.addServlet(holderEvents, "/recv");
        logger.info("hello world 44!");

        // 启动该server，并join使线程启动
        /**
         * join方法实际上是调用了jetty中的线程池，并堵塞当前线程使得server能够优先于当前线程启动，
         * 这样保证了server一定能够启动（如果没有join，那么在程序轻量级的情况下也能够正常运行，
         * 这是得益于Jetty启动速度非常快的原因，当application比较繁杂的时候，必须使用join函数保证server能够优先启动。）
         **/
        try {
            server.start();
            logger.info("hello world 55!");
            // 服务器对象的状态转储到可追加的系统错误控制台
            //server.dump(System.err);
            logger.info("hello world 66!");
            server.join();
            logger.info("hello world 77!");
        } catch (Throwable t) {
            t.printStackTrace(System.err);
        }
    }
}
